-- 秒杀脚本
-- 参数说明:
-- ARGV[1]: 活动ID
-- ARGV[2]: 用户ID
-- ARGV[3]: 商品ID
-- ARGV[4]: 购买数量
-- ARGV[5]: 订单号
-- 
-- 返回值说明:
-- 0 - 商品不存在或库存键不存在
-- 1 - 秒杀成功
-- 3 - 库存不足
-- 5 - 商品未设置购买限制
-- 6 - 超出用户购买限制

local activityId = ARGV[1]
local userId = ARGV[2]
local productId = ARGV[3]
local quantity = tonumber(ARGV[4]) or 1
local orderNo = ARGV[5]
local defaultExpireSeconds = 86400
local extraHours = 4 * 3600  -- 4小时的秒数

local stockKey = 'seckill:activity:stock:' .. activityId .. ':' .. productId
local limitKey = 'seckill:activity:limit:' .. activityId .. ':' .. productId
local userPurchaseKey = 'seckill:activity:purchased:' .. activityId .. ':' .. productId .. ':' .. userId
local orderKey = 'seckill:activity:order:' .. orderNo
local orderMappingKey = 'seckill:activity:order:mapping:' .. activityId .. ':' .. userId .. ':' .. productId

local limitNum = tonumber(redis.call('get', limitKey) or '0')
if not limitNum or limitNum <= 0 then
    return 5
end

local currentPurchaseNum = tonumber(redis.call('get', userPurchaseKey) or '0')
local totalPurchase = currentPurchaseNum + quantity

if totalPurchase > limitNum then
    return 6
end

local stock = redis.call('get', stockKey)
if not stock then
    return 0
end

local stockNum = tonumber(stock) or 0
if stockNum < quantity then
    return 3
end

-- 获取库存key的剩余过期时间
local stockTtl = redis.call('ttl', stockKey)
-- 计算订单相关数据的过期时间：库存剩余过期时间 + 4小时
-- 如果库存没有设置过期时间(ttl返回-1)或过期时间为-2(键不存在)，则使用默认值
local orderExpireSeconds = defaultExpireSeconds
if stockTtl > 0 then
    orderExpireSeconds = stockTtl + extraHours
end

redis.call('decrby', stockKey, quantity)
redis.call('set', userPurchaseKey, totalPurchase)
redis.call('expire', userPurchaseKey, orderExpireSeconds)

local orderInfo = '{"orderNo":"' .. orderNo .. '","userId":"' .. userId .. '","productId":"' .. productId .. '","quantity":"' .. quantity .. '","activityId":"' .. activityId .. '"}'
redis.call('set', orderKey, orderInfo)
redis.call('expire', orderKey, orderExpireSeconds)

redis.call('sadd', orderMappingKey, orderNo)
redis.call('expire', orderMappingKey, orderExpireSeconds)

return 1